package model.extras.bitArray;

public class BitArray {

	private static final boolean T = true;
	private static final boolean F = false;
	private static final int CANT_BITS = 32;
	private static final long MAX_VALUE = (long)Math.pow(2,CANT_BITS)-1;
	
	private boolean[] aDatos;
	
	
	public BitArray() {
		aDatos=new boolean[CANT_BITS];
		
		for (int i=0; i<aDatos.length; i++)
			aDatos[i]=F;	
	}
	
	public BitArray(long xNumero) throws BitArrayException {
		
		if ((xNumero >= 0) && (xNumero <= MAX_VALUE)) {
			
			aDatos=new boolean[CANT_BITS];

			for (int i=0; i<aDatos.length; i++)
				aDatos[i]=F;	
		
			String tempDatos = Long.toBinaryString(xNumero);
		
			for (int i=0;i<tempDatos.length();i++){			
				if (tempDatos.charAt(i)=='1')
					aDatos[(aDatos.length-tempDatos.length())+i]=T;
			}
		}
		else {
			throw new BitArrayException("Intentó ingresar un número fuera de rango: "+xNumero+". RANGO POSIBLE: [0-"+MAX_VALUE+"].");
		}
	}
	
	public boolean BitAt(int xPosicion) throws BitArrayException {
		
		if ((xPosicion>=0) && (xPosicion<aDatos.length)) {
			return aDatos[xPosicion];
		}
		else {
			throw new BitArrayException("Intentó acceder a un bit fuera de rango: "+xPosicion+". MAXIMO POSIBLE: "+(aDatos.length-1)+".");
		}
		
	}
	
	public int Length() {
		return aDatos.length;		
	}
	
	public void SetPiso() {		
		for (int i=0; i<aDatos.length; i++)
			aDatos[i]=F;		
	}
	
	public void SetTecho() {		
		for (int i=0; i<aDatos.length; i++)
			aDatos[i]=T;		
	}
	
	public void SetNumero(long xNumero) throws BitArrayException {
		
		if ((xNumero >= 0) && (xNumero <= MAX_VALUE)) {
		
			for (int i=0; i<aDatos.length; i++)
				aDatos[i]=F;	
		
			String tempDatos = Long.toBinaryString(xNumero);
				
			for (int i=0;i<tempDatos.length();i++){			
				if (tempDatos.charAt(i)=='1')
					aDatos[(aDatos.length-tempDatos.length())+i]=T;
			}
		}
		else {
			throw new BitArrayException("Intentó ingresar un número fuera de rango: "+xNumero+". RANGO POSIBLE: [0-"+MAX_VALUE+"].");
		}

	}
	
	public long GetNumero() {
		
		long Temp=0;
		
		for (int i=0; i<aDatos.length; i++) {
			if (aDatos[i]==T)
				Temp+=(Math.pow(2,(aDatos.length-1)-i));			
		}
		
		return Temp;
	}
	
	public void ResetBitArray() {
		for (int i=0; i<aDatos.length; i++)
			aDatos[i]=F;
	}	
	
	public void PutBitOF(boolean xBit) {	
		for (int i=0; i<aDatos.length-1; i++)
			aDatos[i]=aDatos[i+1];

		aDatos[aDatos.length-1]=xBit;
	}
	
	public void PutBitUF(boolean xBit) {
		for (int i=1; i<aDatos.length-1; i++)
			aDatos[i]=aDatos[i+1];

		aDatos[aDatos.length-1]=xBit;
	}
		
	public static BitArray CompletarBits(int xNumeroBits, BitArray xArrayACompletar, boolean xModoOperacion, boolean xLimite) throws BitArrayException {
		
		boolean[] DatosTemp = new boolean[CANT_BITS];
		
		for (int i=0; i<DatosTemp.length; i++)
			DatosTemp[i]=F;	
		
		String BitsArrayACompletar = Long.toBinaryString(xArrayACompletar.GetNumero());
				
		for (int i=0;i<BitsArrayACompletar.length();i++){			
			if (BitsArrayACompletar.charAt(i)=='1')
				DatosTemp[(DatosTemp.length-BitsArrayACompletar.length())+i]=T;
		}
				
		if (xModoOperacion==true) { //Overflow
			for (int i=xNumeroBits;i<DatosTemp.length;i++)			
				DatosTemp[i-xNumeroBits]=DatosTemp[i];
	
			for (int i=DatosTemp.length-xNumeroBits;i<DatosTemp.length;i++)			
				DatosTemp[i]=xLimite;
		}
		else //Underflow
		{
			for (int i=xNumeroBits+1;i<DatosTemp.length;i++)			
				DatosTemp[i-xNumeroBits]=DatosTemp[i];
	
			for (int i=DatosTemp.length-xNumeroBits;i<DatosTemp.length;i++)			
				DatosTemp[i]=xLimite;			
		}
		
		long ResultadoTemp=0;
		
		for (int i=0; i<DatosTemp.length; i++) {
			if (DatosTemp[i]==T)
				ResultadoTemp+=(Math.pow(2,(DatosTemp.length-1)-i));			
		}
				
		BitArray ReturnValue = new BitArray(ResultadoTemp);
		
		return ReturnValue;		
	}	
	
	public String ToBinaryString() {
		
		String Salida = new String();
		
		for (int i=0; i<aDatos.length; i++) {
			if (aDatos[i]==T)
				Salida = Salida.concat("1");
			else
				Salida = Salida.concat("0");
		}		
		
		return Salida;
	}
	
	
	public void PrintDatos() {
		System.out.println("");
		System.out.print("[");
		for (int i=0; i<aDatos.length; i++) {
			if (aDatos[i]==T)
				System.out.print("1");
			else
				System.out.print("0");
		}
		System.out.print("]");
		System.out.println("");		
	}
}
